﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Net;
using System.Collections;

namespace HY.Utility.Net
{
    public static class HttpHelper
    {
        public delegate void NetErrorEventHandler(int httpstatuscode, string exception);
        public static NetErrorEventHandler OnNetError;
        static HttpHelper()
        {
            Init();
        }

        public static string GetFullUrl(string url, string suburl)
        {
            if (suburl.StartsWith("http://") || suburl.StartsWith("https://"))
                return url;
            return new Uri(new Uri(url), suburl).ToString();
        }

        private static void Init()
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            System.Net.ServicePointManager.DefaultConnectionLimit = 1024;
            System.Net.ServicePointManager.Expect100Continue = false;
        }


        public static string SendHttpRequest(ref HttpHead head)
        {
            string result = "";
            HttpWebRequest req = null;
            HttpWebResponse rep = null;
            Encoding encoding = Encoding.Default;
            try
            {
                req = (HttpWebRequest)HttpWebRequest.Create(head.Url);
                req.Headers["Accept-Encoding"] = "gzip, deflate";
                if (head.Ajax)
                    req.Headers["X-Requested-With"] = "XMLHttpRequest";
                if (head.ExtendHead != null)
                {
                    foreach (var kv in head.ExtendHead)
                        req.Headers[kv.Key] = kv.Value;
                }
                if (!string.IsNullOrEmpty(head.ContentType))
                    req.ContentType = head.ContentType;

                if (!string.IsNullOrEmpty(head.Cookie))
                    req.Headers["Cookie"] = head.Cookie;
                
                req.Method = head.Method;
                
                if (req.Method == "POST")
                {
                    if (string.IsNullOrEmpty(head.ContentType))
                        req.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";

                    if (!string.IsNullOrEmpty(head.Data))
                    {
                        using (var sw = req.GetRequestStream())
                        {
                            byte[] sdata = Encoding.UTF8.GetBytes(head.Data);
                            sw.Write(sdata, 0, sdata.Length);
                        }
                    }
                    if (!string.IsNullOrEmpty(head.ContentType))
                        req.ContentType = head.ContentType;
                }

                if (!string.IsNullOrEmpty(head.Referer))
                    req.Referer = head.Referer;

                req.Method = head.Method;
                req.KeepAlive = head.KeepAlive;
                req.UserAgent = //"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E)"; 
                    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36";
                req.Timeout = 60 * 1000;
                req.AllowAutoRedirect = head.AllowAutoRedirect;

                ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(delegate { return true; });
                rep = (HttpWebResponse)req.GetResponse();
                head.Result_SetCookie = rep.Headers["Set-Cookie"];
                head.Result_StatusCode = rep.StatusCode;
                if (rep.StatusCode == HttpStatusCode.Found)
                    head.Result_RedirectUrl = rep.Headers["Location"] == null ? "" : rep.Headers["Location"];
                if (rep.ContentType != null)
                {
                    string contenttype = rep.ContentType.ToLower();
                    if (contenttype.IndexOf("utf-8") != -1)
                        encoding = Encoding.UTF8;
                }
                if (rep.ContentEncoding == "gzip")
                {
                    using (GZipStream gzip = new System.IO.Compression.GZipStream(rep.GetResponseStream(), CompressionMode.Decompress))
                    {
                        using (StreamReader sr = new StreamReader(gzip, encoding))
                        {
                            result = sr.ReadToEnd();
                        }
                    }
                }
                else if (rep.ContentEncoding == "deflate")
                {
                    using (DeflateStream gzip = new DeflateStream(rep.GetResponseStream(), CompressionMode.Decompress))
                    {
                        using (StreamReader sr = new StreamReader(gzip, encoding))
                        {
                            result = sr.ReadToEnd();
                        }
                    }
                }
                else
                {
                    using (StreamReader sr = new StreamReader(rep.GetResponseStream(), encoding))
                    {
                        result = sr.ReadToEnd();
                    }
                }
                head.Result_Success = true;
            }
            catch (Exception ex)
            {
                head.Result_Exception = ex.Message;
                OnNetError?.Invoke((int)head.Result_StatusCode, ex.Message);
            }
            finally
            {
                if (rep != null)
                {
                    rep.Close();
                    rep = null;
                }
                if (req != null)
                {
                    req.Abort();
                    req = null;
                }
            }
            return result;
        }
    }
}
